package org.geekbang.thinking.in.spring.ioc.dependency.source;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.io.ResourceLoader;

import javax.annotation.PostConstruct;

/**
 * 依赖来源示例
 *
 * @author wangyh2
 * @version v1.0
 * @since 2021-09-30 09:35
 */
public class DependencySourceDemo {

    /**
     * 注入在 postProcessProperties 方法执行，早于 setter注入，也早于 @PostConstruct
     * 注入四个初始话Bean的时候 注入的四个类型对象，(注意: 该四个对象不在Bean容器中,不可以通过getBean获取,只能注入)
     *
     * @see org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory
     */
    @Autowired
    BeanFactory beanFactory;
    @Autowired
    ResourceLoader resourceLoader;
    @Autowired
    ApplicationEventPublisher applicationEventPublisher;
    @Autowired
    ApplicationContext applicationContext;

    @PostConstruct
    public void initByInjection() {
        System.out.println("beanFactory == applicationContext " + (beanFactory == applicationContext));
        System.out.println("beanFactory == applicationContext.getBeanFactory() " + (beanFactory == applicationContext.getAutowireCapableBeanFactory()));
        System.out.println("resourceLoader == applicationContext " + (resourceLoader == applicationContext));
        System.out.println("ApplicationEventPublisher == applicationContext " + (applicationEventPublisher == applicationContext));
    }

    @PostConstruct
    public void initByLookup() {
        getBean(BeanFactory.class);
        getBean(ApplicationContext.class);
        getBean(ResourceLoader.class);
        getBean(ApplicationEventPublisher.class);
    }


    /**
     * GetBean方法
     */
    private <T> T getBean(Class<T> beanType) {
        try {
            return beanFactory.getBean(beanType);
        } catch (NoSuchBeanDefinitionException e) {
            System.err.println("当前类型" + beanType.getName() + " 无法在 BeanFactory 中查找!");
        }
        return null;
    }

    public static void main(String[] args) {
        // 1,创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 2,注册 Configuration Class（配置类） -> Spring Bean
        applicationContext.register(DependencySourceDemo.class);
        // 3,启动 Spring 应用上下文
        applicationContext.refresh();
        // 4,依赖查找 DependencySourceDemo Bean
        applicationContext.getBean(DependencySourceDemo.class);
        // 5,显示地关闭 Spring 应用上下文
        applicationContext.close();
    }
}
